package com.generator.code;

import com.generator.common.MysqlUtil;
import com.generator.common.api.BiGenerator;
import com.generator.common.api.build.*;
import com.generator.common.bean.DatabaseBean;
import com.generator.common.bean.SystemConfigBean;
import com.generator.common.bean.TableColumnBean;
import com.generator.common.enums.DbType;
import com.generator.common.util.*;
import com.generator.view.bean.GeneratorConfig;
import org.apache.log4j.Logger;

import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;

import static com.generator.common.constant.BaseConstant.DOT;

/**
 * 负责mybatis部分代码生成
 *
 * @author syl
 * @create 2018-04-03 10:59
 **/
public class MybatisCodeGenerator {
    private static final Logger LOG = Logger.getLogger(MybatisCodeGenerator.class);
    private static final List<String> DTO_MATCHING_TYPE = new ArrayList<>();//日期类型匹配项
    private static final boolean SERIALIZABLE = ConfigReadUtil.getYmlBoolean("generate.serializable");

    static {
        DTO_MATCHING_TYPE.add("date");
        DTO_MATCHING_TYPE.add("datetime");
        DTO_MATCHING_TYPE.add("time");
        DTO_MATCHING_TYPE.add("timestamp");
    }

    private SystemConfigBean systemConfig;
    private String beanName;
    private String functionTarget;
    private String functionName;
    private String projectFolder;
    private String xmlDirectory;
    private String basePath;
    private String mapperPath;

    public MybatisCodeGenerator(GeneratorConfig config, DatabaseBean databaseBean) {
        databaseBean.setTableName(config.getTableName());
        String FS = File.separator;
//        SqlLiteMapper dao = DbConnectionUtil.getSqliteDao();
        LOG.info("SingletonMap.getInstance().getValueByKey(\"name\"):" + SingletonMap.getInstance().getValueByKey("name"));
//        this.systemConfig  = dao.getSystemConfig(SingletonMap.getInstance().getValueByKey("username"));

        this.systemConfig = MysqlUtil.selectSystemConfig(SingletonMap.getInstance().getValueByKey("username"));
        this.beanName = config.getDomainObjectName();
        this.functionTarget = config.getFunctionTarget();
        this.functionName = functionTarget.substring(functionTarget.lastIndexOf(DOT) + 1);
        this.projectFolder = config.getProjectFolder();
        this.xmlDirectory = config.getXmlDirectoryFull();
        this.basePath = projectFolder + config.getJavaDirectory() + FS;
        String temp = basePath + functionTarget.replace(DOT, FS) + FS + "mapper/xml" + FS;
        this.mapperPath = StringUtils.isEmpty(xmlDirectory) ? temp : projectFolder + xmlDirectory + FS + functionName + FS;

        startGenerator(config, databaseBean);//开始生成
    }

    public void startGenerator(GeneratorConfig config, DatabaseBean databaseBean) {
        boolean actualColumnName = config.isUseActualColumnName();
        List<TableColumnBean> columnList = DbConnectionUtil.getTableColumnList(databaseBean, 1);
        //生成普通pojo start
        JavaBeanBuild javaBeanBuild = new JavaBeanBuild(basePath, beanName, functionTarget, systemConfig, config.isAssistStatic())
                .setLombok(config.isLombok()).setRemark(config.getTableComment() + " POJO")
                .addAllFiled(columnList, config.isUseActualColumnName());
        LOG.info("bean reference " + javaBeanBuild.getReference());
        if (SERIALIZABLE) {
            javaBeanBuild.addJimplements("Serializable").addImport("java.io.Serializable");
        }

        new BiGenerator(javaBeanBuild, true);
        //生成普通pojo end

        //生成DTO pojo start
//        JavaBeanBuild dtoBuild = new JavaBeanBuild(basePath, beanName + "DTO", functionTarget,systemConfig,false)
//                .setLombok(config.isLombok()).setRemark(config.getTableComment()+" DTO")
//                .addAllFiled(initMoreColumn(columnList),actualColumnName);
//
//        if(SERIALIZABLE){
//            dtoBuild.addJimplements("Serializable").addImport("java.io.Serializable");
//        }
//        LOG.info("bean reference "+dtoBuild.getReference());
//        new BiGenerator(dtoBuild, true);
        //生成DTO pojo end

        //生成DAO 接口
        DaoBuild daoBuild = new DaoBuild(basePath, config, systemConfig)
                .setRemark(config.getTableComment() + "类 Dao")
                .setJavaBeanReference(javaBeanBuild.getReference())
//                .setDtoReference(dtoBuild.getReference())
                .addAllFiled(columnList, actualColumnName);
        new BiGenerator(daoBuild, true);

        ServiceBuild serviceBuild = null;
        //生成service接口
        if (config.isGeneratorService()) {
            serviceBuild = new ServiceBuild(basePath, config, systemConfig)
                    .setBeanReference(javaBeanBuild.getReference())
//                    .setDtoReference(dtoBuild.getReference())
            ;
            new BiGenerator(serviceBuild, true);
        }
        if (config.isGeneratorServiceImpl() && serviceBuild != null) {
            ServiceImplBuild serviceImplBuild = new ServiceImplBuild(basePath, config, systemConfig, daoBuild.getReferencePackage(), daoBuild.getDaoName())
                    .setBeanReference(javaBeanBuild.getReference())
//                    .setDtoReference(dtoBuild.getReference())
//            .setDaoReference(daoBuild.getReference())
                    .setServiceReference(serviceBuild.getReference());
            new BiGenerator(serviceImplBuild, true);
        }

        //生成mapper
//        MapperBuild generatorMapperBuild = new MapperBuild(mapperPath, config, DbType.valueOf(databaseBean.getDbType()),false,config.isAutoIncrement())
//            .setNamespace(daoBuild.getReference())
//                .setBeanReference(javaBeanBuild.getReference())
//            .addAllFiled(columnList, initMoreColumn(columnList),actualColumnName)
//            .setSystemConfig(systemConfig);

        MapperBuild simpleMapperBuild = new MapperBuild(mapperPath, config, DbType.valueOf(databaseBean.getDbType()), true)
                .setNamespace(daoBuild.getReference()).setBeanReference(javaBeanBuild.getReference())
                .addAllFiled(columnList, initMoreColumn(columnList), actualColumnName).setSystemConfig(systemConfig);


//        new BiGenerator(generatorMapperBuild,true);
        //供新增sql添加的mapper
        new BiGenerator(simpleMapperBuild, true);
        String osName = System.getProperty("os.name");
        if (osName != null) {
            if (osName.contains("Mac")) {
                try {
                    Runtime.getRuntime().exec("open " + this.basePath);
                } catch (IOException e) {
                    e.printStackTrace();
                }
            } else if (osName.contains("Windows")) {
                try {
                    Runtime.getRuntime().exec("cmd /c start " + this.basePath);
                } catch (IOException e) {
                    e.printStackTrace();
                }
            } else {
                LOG.debug("文件输出目录:" + this.basePath);
            }
        }

        LOG.info("======MybatisCodeGenerator生成完成=======");
    }

    /**
     * 初始化更多 列
     *
     * @param list
     * @return
     */
    private List<TableColumnBean> initMoreColumn(List<TableColumnBean> list) {
        List<TableColumnBean> tempList = CommonUtil.deepCopy(list);
        for (TableColumnBean bean : list) {
            String type = bean.getColumnType();
            if (DTO_MATCHING_TYPE.contains(type.toLowerCase())) {
                String name = bean.getColumnName();
                String comment = bean.getColumnComment();
                TableColumnBean temp1 = new TableColumnBean();
                temp1.setColumnType(type).setColumnName(name + "Start").setOriginalColumnName(name)
                        .setColumnComment("按" + name + "的开始时间查找").setAcquired(true).setSymbol("&gt;");
                TableColumnBean temp2 = new TableColumnBean();
                temp2.setColumnType(type).setColumnName(name + "End").setOriginalColumnName(name)
                        .setColumnComment("按" + name + "的截止时间查找").setAcquired(true).setSymbol("&lt;");
                tempList.add(temp1);
                tempList.add(temp2);
            }
        }
        return tempList;
    }

}
